home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 January / CHIP Turkiye Ocak 1997.iso / program / sound / amod30 / adnmod.pas < prev    next >
Pascal/Delphi Source File  |  1995-08-12  |  46KB  |  1,975 lines

  1. {$m 6000,58000,58000}
  2. uses crt,dos,modunit,modtypes,memunit,list,txt3d;
  3. const
  4. _c1 = 1;
  5. _Db1 = 2;
  6. _D1 = 3;
  7. _Eb1 = 4;
  8. _E1 = 5;
  9. _F1 = 6;
  10. _Gb1 = 7;
  11. _G1 = 8;
  12. _Ab1 = 9;
  13. _A1 = 10;
  14. _Bb1 = 11;
  15. _B1 = 12;
  16.  
  17. _c2 = 1+12;
  18. _Db2 = 2+12;
  19. _D2 = 3+12;
  20. _Eb2 = 4+12;
  21. _E2 = 5+12;
  22. _F2 = 6+12;
  23. _Gb2 = 7+12;
  24. _G2 = 8+12;
  25. _Ab2 = 9+12;
  26. _A2 = 10+12;
  27. _Bb2 = 11+12;
  28. _B2 = 12+12;
  29.  
  30. _c3 = 1+24;
  31. _Db3 = 2+24;
  32. _D3 = 3+24;
  33. _Eb3 = 4+24;
  34. _E3 = 5+24;
  35. _F3 = 6+24;
  36. _Gb3 = 7+24;
  37. _G3 = 8+24;
  38. _Ab3 = 9+24;
  39. _A3 = 10+24;
  40. _Bb3 = 11+24;
  41. _B3 = 12+24;
  42.  
  43. col_backr = 0;
  44. col_backg = 0;
  45. col_backb = 10;
  46. col_back = 2;
  47. col_flash = 20;
  48. flash_val : integer= 0;
  49. strobo_speed : integer = 8;
  50.  
  51. per_txt : array[0..48] of string[3] = ('   ',
  52.           'C-1','C#1','D-1','D#1','E-1','F-1',
  53.           'F#1','G-1','G#1','A-1','A#1','B-1',
  54.           'C-2','C#2','D-2','D#2','E-2','F-2',
  55.           'F#2','G-2','G#2','A-2','A#2','B-2',
  56.           'C-3','C#3','D-3','D#3','E-3','F-3',
  57.           'F#3','G-3','G#3','A-3','A#3','B-3',
  58.           'C-4','C#4','D-4','D#4','E-4','F-4',
  59.           'F#4','G-4','G#4','A-4','A#4','B-4');
  60. hex_tbl : array[0..15] of char = ('0','1','2','3','4','5','6','7',
  61.                                   '8','9','A','B','C','D','E','F');
  62. fx_txt : array[0..15] of string[3] = (        {downcase means fx not}
  63.          'ARP','PR^','PRv','TON','vib','T&S', {correctly supported}
  64.          'V&S','trm','---','SO=','VLs','JMP',
  65.          'VL=','BRK','EFX','SPD');
  66.  
  67. efx_txt : array[0..15] of string[4] = (
  68.          'filt','FPR^','FPRv','glis','vibf',
  69.          'FTUN','loop','trmf','PAN=','TRIG',
  70.          'FVL^','FVLv','NCUT','NDEL','pdel',
  71.          'funk');
  72.  
  73. savertime : integer = 18*60*5;
  74.  
  75. defpan : array[0..11] of integer = (3,12,12,3,3,12,12,3,3,12,12,3);
  76. pan_sign : array[0..11] of integer = (-1,1,1,-1,-1,1,1,-1,-1,1,1,-1);
  77. pan_mode : boolean = false;
  78. pan_speed : integer = 16;
  79. pan_cnt : integer = 16*4;
  80. pan_inc : integer = 1;
  81. qualitymode : boolean = false;
  82.  
  83.   temp_path : string = 'c:\';
  84.   unzip_opt = ' -o';
  85.  
  86. {$i adnpic1.inc}
  87. {$i adnpic2.inc}
  88. {$i adnpic3.inc}
  89. {$i adnpic4.inc}
  90. {$i adnpic5.inc}
  91. {$i adnpic6.inc}
  92.  
  93. var
  94.   gusmem : longint;
  95.   start_sample,cur_sample,play_sample : integer;
  96.   cur_octave : integer;
  97.   old_row : integer;
  98.   mod_name : string;
  99.   pause : byte;
  100.   oldint8,oldint9 : procedure;
  101.   alt_tab : boolean;
  102.   strobo_sam : array[0..31] of boolean;
  103.   strobo_val : integer;
  104.   strobo_col : array[1..3] of integer;
  105.   strobo_fx : boolean;
  106.   help : boolean;
  107.   {golmap1,golmap2 : array[0..51,0..81] of byte;}
  108.   golmap1 : array[0..51,0..81] of byte absolute $b800:8000;
  109.   golmap2 : array[0..51,0..81] of byte absolute $b800:13000;
  110.   normpal,pal : array[0..63,0..2] of byte;
  111.   normkbf : byte;
  112.   int_cnt : integer;
  113.   start_chn : integer;
  114.  
  115.   lpic : pointer;
  116.   listpic : ^t_memarray;
  117.   flist : t_list;
  118.   strlist : array[0..maxline+1] of string[20];
  119.   typelist : array[0..maxline+1] of integer;
  120.   org_path,old_path,cur_path : string;
  121.   drives : array[1..28] of boolean;
  122.   new_mod,archive : boolean;
  123.   oldpertbl : array[0..15,1..48] of word;
  124.  
  125. procedure hide_cursor; assembler;
  126. asm
  127.   mov  ax,0100h
  128.   mov  cx,2607h
  129.   int  10h
  130. end;
  131.  
  132. procedure wait_vr; assembler;
  133. asm
  134.   mov  dx,3dah
  135. @@1:
  136.   in   al,dx
  137.   test al,8
  138.   jz   @@1
  139. end;
  140.  
  141. procedure wait_novr; assembler;
  142. asm
  143.   mov  dx,3dah
  144. @@1:
  145.   in   al,dx
  146.   test al,8
  147.   jnz  @@1
  148. end;
  149.  
  150. procedure setvgapal(pal,col1,col2,col3 : byte); assembler;
  151. asm
  152.   cli
  153.   mov  dx,3c8h
  154.   mov  al,pal
  155.   out  dx,al
  156.   inc  dx
  157.   mov  al,col1
  158.   out  dx,al
  159.   mov  al,col2
  160.   out  dx,al
  161.   mov  al,col3
  162.   out  dx,al
  163.   sti
  164. end;
  165.  
  166. procedure set_scr_ofs(ofs : word); assembler;
  167. asm
  168.   cli
  169.   mov  bx,ofs
  170.   mov  dx,$3d4
  171.   mov  al,0Ch       {Start address high}
  172.   out  dx,al
  173.   inc  dx
  174.   mov  al,bh
  175.   out  dx,al
  176.   dec  dx
  177.   mov  al,0Dh      {Start address high}
  178.   out  dx,al
  179.   inc  dx
  180.   mov  al,bl
  181.   out  dx,al
  182.   sti
  183. end;
  184.  
  185. procedure line_comp(lc : word);
  186. var
  187. b : byte;
  188. begin
  189.   port[$3d4] := 7;
  190.   if lc and 256 > 0 then b := 31
  191.   else b := 15;
  192.   port[$3d5] := b;
  193.   port[$3d4] := 9;
  194.   port[$3d5] := 7;
  195.   port[$3d4] := $18;
  196.   port[$3d5] := lo(lc);
  197. end;
  198.  
  199. procedure getpal(p : pointer); assembler;
  200. asm
  201.   cld
  202.   cli
  203.   mov  es,word ptr p+2
  204.   mov  di,word ptr p
  205.   xor  ax,ax
  206.   mov  dx,3c7h
  207.   out  dx,al
  208.   mov  dx,3c9h
  209.   mov  cx,64*3
  210. @@1:
  211.   in   al,dx
  212.   stosb
  213.   loop @@1
  214.   sti
  215. end;
  216.  
  217. procedure setpal(p : pointer); assembler;
  218. asm
  219.   cld
  220.   cli
  221.   push ds
  222.   mov  ds,word ptr p+2
  223.   mov  si,word ptr p
  224.   xor  ax,ax
  225.   mov  dx,3c8h
  226.   out  dx,al
  227.   inc  dx
  228.   mov  cx,64*3
  229. @@1:
  230.   lodsb
  231.   out  dx,al
  232.   loop @@1
  233.   pop  ds
  234.   sti
  235. end;
  236.  
  237. function fixgetmem(p : pointer) : pointer;
  238. var
  239. hi,lo : word;
  240. p2 : pointer;
  241. begin
  242.   asm
  243.     mov  ax,word ptr p
  244.     mov  lo,ax
  245.     mov  ax,word ptr p+2
  246.     mov  hi,ax
  247.   end;
  248.   if lo <> 0 then hi := hi+(lo+15) div 16;
  249.   asm
  250.     mov  ax,0
  251.     mov  word ptr p2,ax
  252.     mov  ax,hi
  253.     mov  word ptr p2+2,ax
  254.   end;
  255.   fixgetmem := p2;
  256. end;
  257. {$s-}
  258.  
  259. function peekkey : char;
  260. var
  261. c : char;
  262. begin
  263.   c := #0;
  264. asm
  265.   mov  ah,1
  266.   int  16h
  267.   jnz   @@end
  268.   mov  ax,0
  269. @@end:
  270.   mov  c,al
  271. end;
  272.   peekkey := c;
  273. end;
  274.  
  275. procedure fillattr(x,y,xl : integer; attr : byte); assembler;
  276. asm
  277.   mov  ax,0b800h
  278.   mov  es,ax
  279.   mov  di,y
  280.   dec  di
  281.   mov  ax,160
  282.   mul  di
  283.   dec  x
  284.   add  ax,x
  285.   add  ax,x
  286.   mov  di,ax
  287.   inc  di
  288.   mov  cx,xl
  289.   mov  al,attr
  290. @@1:
  291.   mov  es:[di],al
  292.   add  di,2
  293.   loop @@1
  294. end;
  295.  
  296. procedure fastwrite(x,y : word;s : string);
  297. begin
  298. {l := byte(s[0]);
  299. if l = 0 then exit;
  300. for n := 1 to l do mem[$b800:(y-1)*160+(x-1)*2+n*2-2] := byte(s[n]);}
  301. asm
  302.     push ds
  303.     mov  ax,ss
  304.     mov  ds,ax
  305.     mov  ax,0b800h
  306.     mov  es,ax
  307.     lea  si,s
  308.     lodsb
  309.     cmp  al,0
  310.     jne  @@2
  311.     jmp  @@end
  312. @@2:
  313.     mov  cl,al
  314.     xor  ch,ch
  315.     mov  di,y
  316.     dec  di
  317.     dec  x
  318.     mov  ax,160
  319.     mul  di
  320.     mov  di,ax
  321.     add  di,x
  322.     add  di,x
  323. @@1:
  324.     movsb
  325.     inc  di
  326.     loop @@1
  327.     pop  ds
  328. @@end:
  329. end;
  330. end;
  331.  
  332. procedure fastwritel(x,y,l : word;s : string);
  333. begin
  334. asm
  335.     push ds
  336.     mov  ax,ss
  337.     mov  ds,ax
  338.     mov  ax,0b800h
  339.     mov  es,ax
  340.     lea  si,s
  341.     inc  si
  342.     mov  cx,l
  343.     cmp  cx,0
  344.     jne  @@2
  345.     ret
  346. @@2:
  347.     mov  di,y
  348.     dec  di
  349.     dec  x
  350.     mov  ax,160
  351.     mul  di
  352.     mov  di,ax
  353.     add  di,x
  354.     add  di,x
  355. @@1:
  356.     movsb
  357.     inc  di
  358.     loop @@1
  359.     pop  ds
  360. end;
  361. end;
  362.  
  363. procedure scroll_up(y1,yl : word); assembler;
  364. asm
  365.   mov  ax,y1
  366.   mov  cx,160
  367.   mul  cx
  368.   mov  y1,ax
  369.   push ds
  370.   mov  ax,0b800h
  371.   mov  ds,ax
  372.   mov  es,ax
  373.   mov  si,y1
  374.   add  si,160
  375.   mov  di,y1
  376.   mov  bx,yl
  377. @@1:
  378.   mov  cx,80
  379.   rep  movsw
  380.   dec  bx
  381.   jnz  @@1
  382.   pop  ds
  383. end;
  384.  
  385. function byte2hex(b : byte) : string;
  386. begin
  387.   byte2hex := hex_tbl[b shr 4]+hex_tbl[b and 15];
  388. end;
  389.  
  390. function nibb2hex(b : byte) : char;
  391. begin
  392.   nibb2hex := hex_tbl[b and 15];
  393. end;
  394.  
  395. function int2str(i,n : integer) : string;
  396. var
  397. s : string;
  398. begin
  399.   str(i:n,s);
  400.   int2str := s;
  401. end;
  402.  
  403. function word2str(i,n : word) : string;
  404. var
  405. s : string;
  406. begin
  407.   str(i:n,s);
  408.   word2str := s;
  409. end;
  410.  
  411. procedure showbyte(x,y : integer;b : byte); assembler;
  412. asm
  413.   dec  y
  414.   dec  x
  415.   mov  ax,0b800h
  416.   mov  es,ax
  417.   mov  di,y
  418.   mov  ax,160
  419.   mul  di
  420.   mov  di,ax
  421.   add  di,x
  422.   add  di,x
  423.   mov  ah,0
  424.   mov  al,b
  425.   mov  cl,10
  426.   div  cl
  427.   add  ax,3030h
  428.   mov  es:[di],al
  429.   add  di,2
  430.   mov  es:[di],ah
  431. end;
  432.  
  433. procedure showint3(x,y : integer;w : word); assembler;
  434. asm
  435.   dec  y
  436.   dec  x
  437.   mov  ax,0b800h
  438.   mov  es,ax
  439.   mov  di,y
  440.   mov  ax,160
  441.   mul  di
  442.   mov  di,ax
  443.   add  di,x
  444.   add  di,x
  445.   mov  ax,w
  446.   mov  cl,100
  447.   div  cl
  448.   mov  bx,ax
  449.   add  al,30h
  450.   mov  es:[di],al
  451.   add  di,2
  452.   mov  al,bh
  453.   mov  ah,0
  454.   mov  cl,10
  455.   div  cl
  456.   add  ax,3030h
  457.   mov  es:[di],al
  458.   add  di,2
  459.   mov  es:[di],ah
  460. end;
  461.  
  462. procedure showhex(x,y : integer;b : byte);
  463. begin
  464.   mem[$b800:(y-1)*160+2*x-2] := byte(hex_tbl[b shr 4]);
  465.   mem[$b800:(y-1)*160+2*x] := byte(hex_tbl[b and 15]);
  466. end;
  467.  
  468. {$s+}
  469. procedure show_pic(ofs,dest : word;pic : pointer); assembler;
  470. asm
  471.   mov  ax,dest
  472.   mov  es,ax
  473.   mov  dx,0
  474.   mov  ax,700h
  475.   mov  cx,0
  476.   mov  di,ofs
  477.   push ds
  478.   mov  si,word ptr pic
  479.   mov  ds,word ptr pic+2
  480. @@start:
  481.   lodsb
  482.   cmp  al,8
  483.   jae  @@char
  484.   cmp  al,0
  485.   je   @@end
  486.   cmp  al,1
  487.   je   @@attr
  488.   cmp  al,2
  489.   je   @@pack
  490.   cmp  al,3
  491.   je   @@space
  492.   jmp  @@start
  493. @@attr:
  494.   lodsb
  495.   mov  ah,al
  496.   jmp  @@start
  497. @@space:
  498.   lodsb
  499.   mov  cl,al
  500.   mov  al,32
  501.   rep  stosw
  502.   jmp  @@start
  503. @@pack:
  504.   lodsb
  505.   mov  cl,al
  506.   lodsb
  507.   rep  stosw
  508.   jmp  @@start
  509. @@char:
  510.   stosw
  511.   jmp  @@start
  512. @@end:
  513.   pop  ds
  514. end;
  515.  
  516. procedure normscr;
  517. var
  518. n : integer;
  519. begin
  520.   hide_cursor;
  521.   setvgapal(col_back,col_backr,col_backg,col_backb);
  522.   show_pic(8000+0,$b800,@image1);
  523.   show_pic((50+5+header.chns)*160,$b800,@image2);
  524.   show_pic(160,$b800,@image3);
  525.   for n := 0 to header.chns do move(image4,mem[$b800:(4+n)*160+8000],160);
  526.   line_comp((header.chns+9)*8);
  527.   set_scr_ofs(4000);
  528.   if qualitymode then begin
  529.     fastwrite(8,51,'QUALITY MODE');
  530.     fastwrite(62,51,'QUALITY MODE');
  531.   end;
  532. end;
  533.  
  534. function per2note(per : word) : string;
  535. var
  536. n,n2 : integer;
  537. s : string[3];
  538. begin
  539.   n2 := 0;
  540.   for n := 1 to 48 do begin
  541.     if oldpertbl[0,n] = per then begin
  542.       n2 := n;
  543.       n := 48;
  544.     end;
  545.   end;
  546.   if n2 = 0 then if per = 0 then per2note := '...'
  547.   else per2note := '???'
  548.   else per2note := per_txt[n2];
  549. end;
  550.  
  551. procedure makepertbl;
  552. var
  553. n,i : integer;
  554. begin
  555.   if not qualitymode then move(oldpertbl,per_table,sizeof(per_table))
  556.   else for n := 0 to 15 do for i := 1 to 48 do begin
  557.     per_table[n,i] := round(per_table[n,i]*(0.975+random(10)/200));
  558.   end;
  559. end;
  560.  
  561. {$s-}
  562. procedure bar(x,y,l : integer;c : char); assembler;
  563. asm
  564.   cld
  565.   mov  ax,0b800h
  566.   mov  es,ax
  567.  
  568.   mov  di,y
  569.   dec  di
  570.   mov  ax,160
  571.   mul  di
  572.   dec  x
  573.   add  ax,x
  574.   add  ax,x
  575.   mov  di,ax
  576.   cmp  l,0
  577.   jz   @@3
  578.   mov  cx,l
  579.   mov  al,c
  580. @@1:
  581.   stosb
  582.   inc  di
  583.   dec  cx
  584.   jnz  @@1
  585. @@3:
  586.   mov  cx,17
  587.   sub  cx,l
  588.   mov  al,32
  589. @@2:
  590.   stosb
  591.   inc  di
  592.   dec  cx
  593.   jnz  @@2
  594. end;
  595.  
  596. {$s+}
  597. procedure show_sample(sam,x,y : integer);
  598. begin
  599.   fillattr(x,y,3,1);
  600.   fastwrite(x,y,int2str(sam,2));
  601.   if strobo_sam[sam] then fillattr(x,y,28,6)
  602.   else fillattr(x+6,y,22,7);
  603.   if sam = cur_sample then fillattr(x,y,3,15);
  604.   fastwritel(x+6,y,22,samples[sam].name);
  605.   fastwrite(x+31,y,word2str(samples[sam].length,5));
  606.   fastwrite(x+39,y,word2str(samples[sam].loopstart,5));
  607.   fastwrite(x+47,y,word2str(samples[sam].loopend,5));
  608.   if samples[sam].ftune > 7 then
  609.     fastwrite(x+55,y,int2str(samples[sam].ftune or $fff0,2))
  610.   else fastwrite(x+55,y,int2str(samples[sam].ftune,2));
  611.   fastwrite(x+61,y,int2str(samples[sam].volume,2));
  612. end;
  613.  
  614. const
  615. ycol : array[0..73] of byte =
  616. (1,1,
  617. 9,9,
  618. 11,11,
  619. 15,15,
  620. 11,11,
  621. 9,9,
  622. 1,1,
  623. 9,9,
  624. 11,11,
  625. 15,15,
  626. 11,11,
  627. 9,9,
  628. 1,1,
  629. 9,9,
  630. 11,11,
  631. 15,15,
  632. 11,11,
  633. 9,9,
  634. 1,1,
  635. 9,9,
  636. 11,11,
  637. 15,15,
  638. 11,11,
  639. 9,9,
  640. 1,1,
  641. 9,9,
  642. 11,11,
  643. 15,15,
  644. 11,11,
  645. 9,9,
  646. 1,1,
  647. 9,9,
  648. 11,11,
  649. 15,15,
  650. 11,11,
  651. 9,9,
  652. 1,1);
  653.  
  654. const
  655. scroll_txt : string = 'Welcome to ADNMOD 0.30, the special ASSEMBLY ''95 edition.    '+
  656.                       'Notice that this screen saver, like the rest of ADNMOD, '+
  657.                       'runs in textmode... It makes 3d pretty cool, huh?    ';
  658. var
  659. scroll_msg : array[0..1000] of char;
  660. scroll_len : integer;
  661.  
  662. procedure scrsaver;
  663. var
  664. n,count : integer;
  665.  
  666. procedure showgol(yc : integer); assembler;
  667. asm
  668.   push ds
  669.   mov  ax,0b800h
  670.   mov  es,ax
  671.   mov  ds,ax
  672.   mov  di,1
  673.   mov  si,offset golmap1+82+2
  674.   mov  dx,49
  675. @@2:
  676.   mov  cx,80
  677.   pop  ds
  678.   mov  bx,dx
  679.   add  bx,yc
  680.   mov  ah,[bx+offset ycol]
  681.  
  682.   push ds
  683.   mov  bx,es
  684.   mov  ds,bx
  685. @@1:
  686.   mov  al,ds:[si]
  687.   inc  si
  688.   shl  al,5
  689.   add  al,ah
  690.   mov  es:[di],al
  691.   add  di,2
  692.   dec  cx
  693.   jnz  @@1
  694.   add  si,2
  695.   dec  dx
  696.   jnz  @@2
  697.   pop  ds
  698. end;
  699.  
  700. procedure muunnagol;
  701. begin
  702.   asm
  703.      push ds
  704.      mov  ax,0b800h
  705.      mov  ds,ax
  706.      mov  es,ax
  707.      mov  di,offset golmap2+82+1
  708.      mov  si,offset golmap1+82+1
  709.      mov  dx,49
  710. @@yloop:
  711.  
  712.      mov  cx,81-1
  713.      mov  bx,81
  714.      inc  si
  715.      inc  di
  716. @@xloop:
  717.      mov  al,[si-81-2]
  718.      add  al,[si-81-1]
  719.      add  al,[si-81]
  720.      add  al,[si-1]
  721.      add  al,[si+1]
  722.      add  al,[si+81]
  723.      add  al,[si+81+1]
  724.      add  al,[si+81+2]
  725.      mov  ah,[si]
  726.      cmp  al,3
  727.      je   @@live
  728.      cmp  ah,0
  729.      je   @@die_scum
  730.      cmp  al,2
  731.      je   @@live
  732. @@die_scum:
  733.      xor  al,al
  734.      stosb
  735.      jmp  @@loop_end
  736. @@live:
  737.      mov  al,1
  738.      stosb
  739. @@loop_end:
  740.      inc  si
  741.      loop @@xloop
  742.      inc  si
  743.      inc  di
  744.  
  745.      dec  dx
  746.      jnz  @@yloop
  747. @@end:
  748.      pop  ds
  749. end;
  750.   move(golmap2,golmap1,sizeof(golmap1));
  751. end;
  752.  
  753. procedure plot(x,y : integer);
  754. var
  755. _x,_y : integer;
  756. begin
  757.   for _y := -2 to 2 do for _x := -2 to 2 do
  758.     golmap1[y+_y,x+_x] := random(2);
  759. end;
  760.  
  761. procedure initgol;
  762. var
  763. n : integer;
  764. begin
  765.   fillchar(golmap1,sizeof(golmap1),0);
  766.   fillchar(golmap2,sizeof(golmap2),0);
  767.   for n := 1 to 20 do plot(random(70)+5,random(40)+5);
  768. end;
  769.  
  770. procedure fadeout;
  771. var
  772. n,i : integer;
  773. begin
  774.   for n := 30 downto 0 do begin
  775.     wait_vr;
  776.     for i := 0 to 63 do
  777.       setvgapal(i,pal[i,0]*n div 30,pal[i,1]*n div 30,pal[i,2]*n div 30);
  778.   end;
  779. end;
  780.  
  781. procedure fadein;
  782. var
  783. n,i : integer;
  784. begin
  785.   for n := 0 to 30 do begin
  786.     wait_vr;
  787.     for i := 0 to 63 do
  788.       setvgapal(i,pal[i,0]*n div 30,pal[i,1]*n div 30,pal[i,2]*n div 30);
  789.   end;
  790. end;
  791.  
  792. procedure scroll(sc : integer);
  793. var
  794. n : integer;
  795. begin
  796.   for n := 0 to 79 do memw[$b800:49*160+n*2] := 15*256+byte(scroll_msg[sc+n]);
  797. end;
  798.  
  799. type
  800. ta = array[0..50000] of byte;
  801. pa = ^ta;
  802.  
  803. var
  804. yc : integer;
  805. pspeed,i : integer;
  806. obj_kx,obj_ky,obj_kz : integer;
  807. buf,p : pointer;
  808. sc,sc2 : integer;
  809.  
  810. begin
  811.   scroll_len := byte(scroll_txt[0])+102;
  812.   fillchar(scroll_msg,sizeof(scroll_msg),0);
  813.   move(scroll_txt[1],scroll_msg[82],scroll_len-102);
  814.   getmem(p,16000+16);
  815.   buf := ptr(seg(p^)+1,0);
  816.   fillchar(buf^,16000,0);
  817.   txt3d.scr_seg := seg(buf^);
  818.   obj_kx := 0;
  819.   obj_ky := 0;
  820.   obj_kz := 0;
  821.   pan_cnt := pan_cnt*5 div 7;
  822.   pspeed := (pan_speed*5) div 7;
  823.   if pspeed < 1 then pspeed := 1;
  824.   getpal(@pal);
  825.   fadeout;
  826.   fillchar(mem[$b800:0],160*100,0);
  827.   textmode(font8x8+co80);
  828.   setfont;
  829.   hide_cursor;
  830.   init3d;
  831.   l3d_asm95;
  832.   initgol;
  833.   count := 0;
  834.   yc := 0;
  835.   matriisi(matrix,0,0,0);
  836.   rotatep;
  837.   time_counter := 0;
  838.   time_counter2 := 0;
  839.   time_counter3 := 0;
  840.   sc := 0;
  841.   sc2 := 0;
  842.   repeat
  843.     wait_vr;
  844.     mix;
  845.     if time_counter > 0 then begin
  846.       inc(yc);
  847.       if yc > 10 then yc := 0;
  848.       showgol(yc);
  849.       muunnagol;
  850.       inc(sc2);
  851.       if sc2 > scroll_len*2 then sc2 := 0;
  852.       sc := sc2 div 2;
  853.       dec(time_counter);
  854.       inc(count);
  855.       if count mod (6*30) = 0 then case random(4) of
  856.         0 : l3d_cube;
  857.         1 : l3d_pyramid;
  858.         2 : l3d_adnmod;
  859.         3 : l3d_asm95;
  860.       end;
  861.       if count > 18*20 then begin
  862.         time_counter := 0;
  863.         count := 0;
  864.         initgol;
  865.       end;
  866.     end;
  867.     scroll(sc);
  868.     hide;
  869.     matriisi(matrix,obj_kx,obj_ky,obj_kz);
  870.     rotatep;
  871.     show;
  872.     inc(obj_kx,time_counter3 div 6);
  873.     inc(obj_ky,time_counter3 div 6);
  874.     inc(obj_kz,time_counter3 div 6);
  875.     time_counter3 := 0;
  876.     if obj_kx > 1000 then dec(obj_kx,1000);
  877.     if obj_ky > 1000 then dec(obj_ky,1000);
  878.     if obj_kz > 1000 then dec(obj_kz,1000);
  879.     if pan_mode and (time_counter2 > 0) then begin
  880.       inc(pan_cnt,pan_inc*time_counter2);
  881.       if (pan_cnt<=-pspeed*7-pspeed+1) or
  882.       (pan_cnt>=pspeed*7+pspeed-1) then pan_inc := -pan_inc;
  883.       if pan_cnt < -pspeed*7-pspeed+1 then pan_cnt := -pspeed*7;
  884.       if pan_cnt > pspeed*7+pspeed-1 then pan_cnt := pspeed*8;
  885.       for n := 0 to header.chns-1 do begin
  886.         i := (pan_sign[i]*pan_cnt) div pspeed;
  887.         if i > 0 then
  888.           channels[n].pan := 8+i
  889.         else channels[n].pan := 7+i;
  890.         gussetbalance(n,channels[n].pan);
  891.       end;
  892.       time_counter2 := 0;
  893.     end;
  894.   until keypressed;
  895.   readkey;
  896.   freemem(p,16000+16);
  897.   for n := 0 to 63 do setvgapal(n,0,0,0);
  898.   fillchar(mem[$b800:0],80*100*2,0);
  899.   textmode(co80+font8x8);
  900.   for n := 0 to 63 do setvgapal(n,0,0,0);
  901.   fillchar(mem[$b800:0],80*100*2,0);
  902.   normscr;
  903.   for n := 0 to 24-header.chns do show_sample(n+start_sample,9,n+17);
  904.   old_row := 666;
  905.   fadein;
  906. end;
  907.  
  908. procedure show_chn(chn,st : byte);
  909. var
  910. fx,fxdata : byte;
  911. start : integer;
  912. n : integer;
  913. begin
  914.   start := 5-st+50;
  915.   inc(chn,st);
  916.   fx := channels[chn].fx;
  917.   fxdata := channels[chn].fxdata;
  918.   if channels[chn].on = 1 then
  919.     fastwritel(3,chn+start,22,samples[channels[chn].sample].name)
  920.   else fastwritel(3,chn+start,22,'     ---MUTED---        ');
  921.   fastwrite(30,chn+start,int2str(channels[chn].vol,2));
  922.   fastwritel(34,chn+start,3,per_txt[channels[chn].note]);
  923.   fastwrite(38,chn+start,int2str(channels[chn].per,3));
  924.   fastwrite(43,chn+start,int2str(channels[chn].dper,3));
  925.   fastwrite(54,chn+start,int2str(shortint(channels[chn].pan)-7,2));
  926.   if fx = 14 then
  927.     fastwritel(47,chn+start,5,efx_txt[fxdata shr 4]+nibb2hex(fxdata and 15))
  928.   else if ((fx < 16) and (fx >0)) or ((fx = 0) and (fxdata > 0)) then
  929.     fastwritel(47,chn+start,5,fx_txt[fx]+byte2hex(fxdata))
  930.   else fastwritel(47,chn+start,5,'     ');
  931.   bar(61,chn+start,(channels[chn].bar+2) div 4,'≈');
  932.   if channels[chn].hit <> 0 then begin
  933.     fillattr(3,chn+start,22,15);
  934.     fillattr(30,chn+start,26,15);
  935.     channels[chn].hit := 2;
  936.   end else begin
  937.     fillattr(3,chn+start,22,7);
  938.     fillattr(30,chn+start,26,7);
  939.   end;
  940. end;
  941.  
  942. procedure show_row(ptn,row : integer);
  943. const
  944. wid = 16;
  945. x = 11;
  946. var
  947.   n : integer;
  948.   sam : integer;
  949.   fx,fxdata : byte;
  950.   chn : integer;
  951.   st : integer;
  952.   _ptn : p_pattern;
  953. begin
  954.   _ptn := virt_getptn(ptn);
  955.   st := 13;
  956.   fastwrite(8,st,byte2hex(row)+':');
  957.   for n := 0 to 3 do begin
  958.     chn := start_chn+n;
  959.     fastwrite(n*wid+x+2,st,
  960.       per2note(_ptn^[row*header.chns+chn].per)+' ');
  961.     sam := _ptn^[row*header.chns+chn].sample;
  962.     if sam > 0 then fastwrite(n*wid+x+6,st,byte2hex(sam)+' ')
  963.     else fastwrite(n*wid+x+6,st,'.. ');
  964.     fx := _ptn^[row*header.chns+chn].fx;
  965.     fxdata := _ptn^[row*header.chns+chn].fxdata;
  966.     case fx of
  967.       0 : if fxdata > 0 then
  968.             fastwrite(n*wid+x+9,st,fx_txt[fx]+byte2hex(fxdata))
  969.           else fastwrite(n*wid+x+9,st,'     ');
  970.       1..$D : fastwrite(n*wid+x+9,st,fx_txt[fx]+byte2hex(fxdata));
  971.       $E : fastwrite(n*wid+x+9,st,efx_txt[fxdata shr 4]+nibb2hex(fxdata and 15));
  972.       $F : fastwrite(n*wid+x+9,st,fx_txt[fx]+byte2hex(fxdata));
  973.     else fastwrite(n*wid+x+9,st,'     ');
  974.     end;
  975.   end;
  976. end;
  977.  
  978. procedure show_info(ptn:integer);
  979. var
  980. st : integer;
  981. begin
  982.   st := 50+8 + header.chns;
  983.   fastwrite(30,st,int2str(amp_vol,2));
  984.   fastwrite(41,st,int2str(speed,2));
  985.   if not vblank then fastwrite(53,st,int2str(tempo,3)+'   ')
  986.   else fastwrite(53,st,'VBlank');
  987.   fastwrite(30,st+1,int2str(cur_ptn,2)+'/'+int2str(header.length-1,2));
  988.   fastwrite(41,st+1,int2str(ptn,2)+'/'+int2str(max_ptn-1,2));
  989.   fastwrite(53,st+1,int2str(cur_row,2));
  990. end;
  991.  
  992. procedure updateinfo;
  993. var
  994. i,n : integer;
  995. kbf : byte;
  996. begin
  997.   if not loaded then exit;
  998.   wait_vr;
  999.   if strobo_fx then for i := 0 to header.chns-1 do
  1000.     if (channels[i].hit <> 0) and (channels[i].on <> 0) then
  1001.       if strobo_sam[channels[i].sample]=true then strobo_val := 62;
  1002.   i := strobo_val and strobo_col[3];
  1003.   if i < col_backb then i := col_backb;
  1004.   setvgapal(0,strobo_val and strobo_col[1],
  1005.               strobo_val and strobo_col[2],
  1006.               strobo_val and strobo_col[3]);
  1007.   setvgapal(2,strobo_val and strobo_col[1],
  1008.               strobo_val and strobo_col[2],
  1009.               i);
  1010.   if strobo_val > 0 then dec(strobo_val,strobo_speed);
  1011.   if strobo_val < 0 then strobo_val := 0;
  1012.   dec(flash_val);
  1013.   if flash_val<-19 then flash_val := 20;
  1014.   n := abs(flash_val)+43;
  1015.   setvgapal(col_flash,n,n,n);
  1016.   kbf := mem[$40:$17] and 15;
  1017.   if channels[start_chn].hit=1 then kbf := kbf or $20;
  1018.   if channels[start_chn+1].hit=1 then kbf := kbf or $40;
  1019.   if channels[start_chn+2].hit=1 then kbf := kbf or $10;
  1020.   mem[$40:$17] := kbf;
  1021.   if pan_mode then begin
  1022.     inc(pan_cnt,pan_inc);
  1023.     if (pan_cnt=-pan_speed*7-pan_speed+1) or
  1024.     (pan_cnt=pan_speed*7+pan_speed-1) then pan_inc := -pan_inc;
  1025.     for i := 0 to header.chns-1 do begin
  1026.       n := (pan_sign[i]*pan_cnt) div pan_speed;
  1027.       if n > 0 then
  1028.         channels[i].pan := 8+n
  1029.       else channels[i].pan := 7+n;
  1030.       gussetbalance(i,channels[i].pan);
  1031.     end;
  1032.   end;
  1033.   for i := 0 to header.chns-1 do show_chn(i,0);
  1034.   show_info(orders[cur_ptn]);
  1035. end;
  1036.  
  1037. procedure show_ptn(clear : boolean);
  1038. var
  1039.   ptn : word;
  1040. var
  1041.   i,n : integer;
  1042.   s : string;
  1043.   c : char;
  1044.   helpcnt : integer;
  1045.  
  1046. begin
  1047.   helpcnt := 0;
  1048.   strobo_val := 0;
  1049.   fastwritel(30,50+7+header.chns,20,header.name);
  1050.   for i := 0 to 24-header.chns do show_sample(i+start_sample,9,i+17);
  1051.   if clear then begin
  1052.     s := '                                                                   ';
  1053.     for i := 0 to 7 do fastwritel(8,14+50+header.chns+i,65,s);
  1054.   end;
  1055.   time_counter := 0;
  1056.   repeat
  1057.     updateinfo;
  1058.     ptn := orders[cur_ptn];
  1059.     time_counter2 := 0;
  1060.     if (not help) and (cur_row <> old_row) then begin
  1061.       old_row := cur_row;
  1062.       fillattr(13,13,60,7+2*16);
  1063.       scroll_up(4,8);
  1064.       show_row(orders[cur_ptn],cur_row);
  1065.       fillattr(13,13,60,15+2*16);
  1066.     end;
  1067.     if upcase(peekkey) = 'H' then begin
  1068.       readkey;
  1069.       time_counter := 0;
  1070.       if help then begin
  1071.         show_pic(160,$b800,@image3);
  1072.         fastwritel(30,50+7+header.chns,20,header.name);
  1073.         for i := 0 to 24-header.chns do show_sample(i+start_sample,9,i+17);
  1074.         help := false;
  1075.       end
  1076.       else begin
  1077.         help := true;
  1078.         show_pic(160,$b800,@image5);
  1079.       end;
  1080.     end;
  1081.     if time_counter > savertime then begin
  1082.       time_counter := 0;
  1083.       scrsaver;
  1084.     end;
  1085.   until keypressed;
  1086.   if help then begin
  1087.     show_pic(160,$b800,@image3);
  1088.     help := false;
  1089.   end;
  1090.   mem[$40:$17] := mem[$40:$17] and 15;
  1091. end;
  1092.  
  1093. {$s-,i-}
  1094. procedure int9; interrupt;
  1095. begin
  1096.   if (mem[$40:$17] and 8 > 0) and (port[$60] = $f) then
  1097.     if alt_tab then begin
  1098.       alt_tab := false;
  1099.     end
  1100.     else begin
  1101.       alt_tab := true;
  1102.     end;
  1103.   asm pushf end;
  1104.   oldint9;
  1105. end;
  1106.  
  1107. procedure fwritel(x,y,l : integer;s : pointer); assembler;
  1108. asm
  1109.   push ds
  1110.   mov  ax,word ptr s+2
  1111.   mov  ds,ax
  1112.   mov  ax,0b800h
  1113.   mov  es,ax
  1114.   mov  si,word ptr s
  1115.   inc  si
  1116.   mov  cx,l
  1117.   cmp  cx,0
  1118.   jne  @@2
  1119.   ret
  1120. @@2:
  1121.   mov  di,y
  1122.   dec  di
  1123.   dec  x
  1124.   mov  ax,160
  1125.   mul  di
  1126.   mov  di,ax
  1127.   add  di,x
  1128.   add  di,x
  1129. @@1:
  1130.   movsb
  1131.   inc  di
  1132.   loop @@1
  1133.   pop  ds
  1134. end;
  1135.  
  1136. procedure int8; interrupt;
  1137. var
  1138. n,i,pspeed : integer;
  1139. p : longint;
  1140. fx,fxdata : byte;
  1141. st : integer;
  1142. begin
  1143.   asm pushf end;
  1144.   oldint8;
  1145.   dec(int_cnt);
  1146.   if int_cnt = 0 then begin
  1147.    int_cnt := 14;
  1148.    if alt_tab then begin
  1149.     if pan_mode then begin
  1150.       pspeed := pan_speed;
  1151.       if pspeed < 1 then pspeed := 1;
  1152.       inc(pan_cnt,pan_inc);
  1153.       if (pan_cnt<=-pspeed*8+1) or
  1154.       (pan_cnt>=pspeed*8-1) then pan_inc := -pan_inc;
  1155.       if pan_cnt < -pspeed*8+1 then pan_cnt := -pspeed*7;
  1156.       if pan_cnt > pspeed*8-1 then pan_cnt := pspeed*7;
  1157.     end;
  1158.     st := 50+9+header.chns;
  1159.     showbyte(53,st,cur_row);
  1160.     showbyte(41,st,speed);
  1161.     showbyte(30,st,cur_ptn);
  1162.     showbyte(33,st,header.length-1);
  1163.     showbyte(41,st,orders[cur_ptn]);
  1164.     showbyte(44,st,max_ptn-1);
  1165.     for n := 0 to header.chns-1 do begin
  1166.       dec(strobo_val,3);
  1167.       if strobo_val < 0 then strobo_val := 0;
  1168.       if strobo_fx then begin
  1169.         port[$3c8] := 0;
  1170.         port[$3c9] := strobo_val and strobo_col[1];
  1171.         port[$3c9] := strobo_val and strobo_col[2];
  1172.         port[$3c9] := strobo_val and strobo_col[3];
  1173.       end;
  1174.       if pan_mode then begin
  1175.         i := integer(pan_sign[n]*pan_cnt) div pspeed;
  1176.         if i > 0 then
  1177.           channels[n].pan := 8+i
  1178.         else channels[n].pan := 7+i;
  1179.         gussetbalance(n,channels[n].pan);
  1180.       end;
  1181.       fx := channels[n].fx;
  1182.       fxdata := channels[n].fxdata;
  1183.       p := longint(@samples[channels[n].sample].name)-1;
  1184.       fwritel(3,n+55,22,pointer(p));
  1185.       showbyte(30,n+55,channels[n].vol);
  1186.       fwritel(34,n+55,3,@per_txt[channels[n].note]);
  1187.       showint3(38,n+55,channels[n].per);
  1188.       showint3(43,n+55,channels[n].dper);
  1189.       showbyte(54,n+55,channels[n].pan);
  1190.       if fx = 14 then begin
  1191.         showhex(50,n+55,fxdata and 15);
  1192.         fwritel(47,n+55,4,@efx_txt[fxdata shr 4]);
  1193.       end
  1194.       else if (fx < 16) and (fx >0) then begin
  1195.         fwritel(47,n+55,3,@fx_txt[fx]);
  1196.         showhex(50,n+55,fxdata);
  1197.       end;
  1198.       if fx > 15 then fillchar(mem[$b800:(n+54)*160+46*2],10,0);
  1199.       bar(61,55+n,(channels[n].bar+2) div 4,'≈');
  1200.       if channels[n].hit = 1 then begin
  1201.         fillattr(3,n+55,22,15);
  1202.         fillattr(30,n+55,26,15);
  1203.         if strobo_fx then
  1204.           if strobo_sam[channels[n].sample] then strobo_val := 62;
  1205.       end else begin
  1206.         fillattr(3,n+55,22,7);
  1207.         fillattr(30,n+55,26,7);
  1208.       end;
  1209.     end;
  1210.    end;
  1211.   end;
  1212. end;
  1213. {$s+,i+}
  1214.  
  1215. procedure init_dos;
  1216. var
  1217. n : integer;
  1218. begin
  1219.   gotoxy(1,1);
  1220.   alt_tab := true;
  1221.   int_cnt := 14;
  1222.   getintvec(9,@oldint9);
  1223.   getintvec(8,@oldint8);
  1224.   asm
  1225.     cld
  1226.     mov  ax,0B800h
  1227.     mov  es,ax
  1228.     mov  di,0
  1229.     mov  cx,4000
  1230.     mov  ax,0720h
  1231.     rep  stosw
  1232.   end;
  1233.   mem[$40:$84] := 40-header.chns;
  1234.   set_scr_ofs(4000);
  1235.   line_comp((9+header.chns)*8);
  1236.   setpal(@normpal);
  1237.   setintvec(9,@int9);
  1238.   setintvec(8,@int8);
  1239. end;
  1240.  
  1241. procedure end_dos;
  1242. begin
  1243.   setintvec(8,@oldint8);
  1244.   setintvec(9,@oldint9);
  1245. end;
  1246.  
  1247. procedure initlist;
  1248. var
  1249. f : file;
  1250. n,i,maxdrive : integer;
  1251. s : string;
  1252. begin
  1253.   getmem(lpic,8000);
  1254.   listpic := fixgetmem(lpic);
  1255.   s := getenv('TEMP');
  1256.   if s <> '' then temp_path := s;
  1257.   archive := false;
  1258.   textmode(co80+font8x8);
  1259.   flist.init(maxline,11,3,68,30,listpic);
  1260.   flist.c2x := 21;
  1261.   fillchar(listpic^,8000,0);
  1262.   show_pic(0,seg(listpic^),@image6);
  1263.   getdir(0,org_path);
  1264.   getdir(0,cur_path);
  1265.   fillchar(drives,sizeof(drives),0);
  1266.   drives[1] := true;
  1267.   drives[2] := false;
  1268.   for n := 3 to 28 do if diskfree(n)>-1 then drives[n] := true;
  1269. end;
  1270.  
  1271. function getmodname(s : string) : string;
  1272. var
  1273. f : file;
  1274. s2 : string;
  1275. begin
  1276.   assign(f,s);
  1277.   reset(f,1);
  1278.   blockread(f,s2[1],20);
  1279.   s2[0] := #20;
  1280.   close(f);
  1281.   getmodname := s2;
  1282. end;
  1283.  
  1284. procedure load;
  1285. var
  1286. dirinfo : searchrec;
  1287. n : integer;
  1288. s : string;
  1289. maxstr : integer;
  1290.  
  1291. begin
  1292.   maxstr := 0;
  1293.   findfirst('*.mod',anyfile,dirinfo);
  1294.   while (doserror = 0) and (maxstr < maxline) do begin
  1295.     strlist[maxstr] := dirinfo.name;
  1296.     typelist[maxstr] := t_mod;
  1297.     inc(maxstr);
  1298.     findnext(dirinfo);
  1299.   end;
  1300.   if not archive then begin
  1301.     findfirst('*.zip',anyfile,dirinfo);
  1302.     while (doserror = 0) and (maxstr < maxline) do begin
  1303.       strlist[maxstr] := dirinfo.name;
  1304.       typelist[maxstr] := t_zip;
  1305.       inc(maxstr);
  1306.       findnext(dirinfo);
  1307.     end;
  1308.     findfirst('*.*',$10,dirinfo);
  1309.     while (doserror = 0) and (maxstr < maxline) do begin
  1310.       if dirinfo.attr and $18 <> 0 then begin
  1311.         strlist[maxstr] := dirinfo.name;
  1312.         typelist[maxstr] := t_dir;
  1313.         inc(maxstr);
  1314.       end;
  1315.       findnext(dirinfo);
  1316.     end;
  1317.   end
  1318.   else begin
  1319.     strlist[maxstr] := '..';
  1320.     typelist[maxstr] := t_dir;
  1321.     inc(maxstr);
  1322.   end;
  1323.   dec(maxstr);
  1324.   if not archive then for n := 1 to 28 do if drives[n]=true then begin
  1325.     inc(maxstr);
  1326.     strlist[maxstr] := char(n+64)+':';
  1327.     typelist[maxstr] := t_drive;
  1328.   end;
  1329.   for n := 0 to maxstr do begin
  1330.     case typelist[n] of
  1331.       t_dir : s := 'DIR';
  1332.       t_zip : s := 'ARCHIVE';
  1333.       t_mod : s := getmodname(strlist[n]);
  1334.       else s := '';
  1335.     end;
  1336.     flist.insline(strlist[n],s,'',typelist[n]);
  1337.   end;
  1338.   flist.qsort;
  1339. end;
  1340.  
  1341. procedure unzip(s : string);
  1342. var
  1343. zippath : string;
  1344. begin
  1345.   zippath := fsearch('PKUNZIP.EXE',getenv('PATH'));
  1346.   chdir(temp_path);
  1347.   exec(zippath,s+' *.mod '+unzip_opt);
  1348.   if doserror <> 0 then begin
  1349.     writeln('Dos error ',doserror);
  1350.     delay(500);
  1351.   end;
  1352. end;
  1353.  
  1354. function countfiles(s : string) : integer;
  1355. var
  1356. dir : searchrec;
  1357. n : integer;
  1358. begin
  1359.   n := 0;
  1360.   findfirst(s,anyfile,dir);
  1361.   while doserror = 0 do begin
  1362.     inc(n);
  1363.     findnext(dir);
  1364.   end;
  1365.   countfiles := n;
  1366. end;
  1367.  
  1368. procedure delall;
  1369. var
  1370. s : searchrec;
  1371. f : file;
  1372. begin
  1373.   findfirst('*.mod',anyfile,s);
  1374.   while (doserror = 0) do begin
  1375.     assign(f,s.name);
  1376.     erase(f);
  1377.     findnext(s);
  1378.   end;
  1379. end;
  1380.  
  1381. procedure doit(num : integer);
  1382. var
  1383. n : integer;
  1384. begin
  1385.   if not archive then case flist.lines^[num].t of
  1386.     t_mod : begin
  1387.               clrscr;
  1388.               stop_playing;
  1389.               free_mod;
  1390.               move(oldpertbl,per_table,sizeof(per_table));
  1391.               load_mod(flist.lines^[num].s[0],false);
  1392.               makepertbl;
  1393.               start_playing;
  1394.               new_mod := true;
  1395.               chdir(cur_path);
  1396.               move(listpic^,mem[$b800:0],6400);
  1397.               hide_cursor;
  1398.               flist.draw;
  1399.               hide_cursor;
  1400.             end;
  1401.     t_dir : begin
  1402.               chdir(flist.lines^[num].s[0]);
  1403.               getdir(0,cur_path);
  1404.               flist.delete;
  1405.               load;
  1406.               move(listpic^,mem[$b800:0],6400);
  1407.               flist.draw;
  1408.            end;
  1409.     t_drive : begin
  1410.                 chdir(flist.lines^[num].s[0]);
  1411.                 getdir(0,cur_path);
  1412.                 flist.delete;
  1413.                 load;
  1414.                 move(listpic^,mem[$b800:0],6400);
  1415.                 flist.draw;
  1416.               end;
  1417.     t_zip : begin
  1418.               getdir(0,old_path);
  1419.               cur_path := temp_path;
  1420.               fillchar(mem[$b800:0],6400,0);
  1421.               textattr := 0;
  1422.               gotoxy(1,1);
  1423.               unzip(old_path+'\'+flist.lines^[num].s[0]);
  1424.               textattr := 7;
  1425.               n := countfiles('*.mod');
  1426.               if n = 0 then begin
  1427.                 fillchar(mem[$b800:0],8000,0);
  1428.                 move(listpic^,mem[$b800:0],6400);
  1429.                 hide_cursor;
  1430.                 chdir(old_path);
  1431.                 flist.delete;
  1432.                 load;
  1433.                 flist.draw;
  1434.               end
  1435.               else if n = 1 then begin
  1436.                 archive := false;
  1437.                 flist.delete;
  1438.                 load;
  1439.                 stop_playing;
  1440.                 free_mod;
  1441.                 move(oldpertbl,per_table,sizeof(per_table));
  1442.                 load_mod(flist.lines^[1].s[0],false);
  1443.                 makepertbl;
  1444.                 start_playing;
  1445.                 delall;
  1446.                 new_mod := true;
  1447.                 fillchar(mem[$b800:0],8000,0);
  1448.                 move(listpic^,mem[$b800:0],6400);
  1449.                 hide_cursor;
  1450.                 chdir(old_path);
  1451.                 flist.delete;
  1452.               end
  1453.               else begin
  1454.                 archive := true;
  1455.                 flist.delete;
  1456.                 load;
  1457.                 hide_cursor;
  1458.                 move(listpic^,mem[$b800:0],6400);
  1459.                 flist.draw;
  1460.               end;
  1461.             end;
  1462.   end
  1463.   else begin
  1464.     if flist.lines^[num].t = t_mod then begin
  1465.       chdir(temp_path);
  1466.       stop_playing;
  1467.       free_mod;
  1468.       move(oldpertbl,per_table,sizeof(per_table));
  1469.       load_mod(flist.lines^[num].s[0],false);
  1470.       makepertbl;
  1471.       start_playing;
  1472.       new_mod := true;
  1473.       fillchar(mem[$b800:0],8000,0);
  1474.       move(listpic^,mem[$b800:0],6400);
  1475.       flist.draw;
  1476.       hide_cursor;
  1477.     end
  1478.     else begin
  1479.       archive := false;
  1480.       chdir(temp_path);
  1481.       delall;
  1482.       chdir(old_path);
  1483.       cur_path := old_path;
  1484.       flist.delete;
  1485.       load;
  1486.       hide_cursor;
  1487.       move(listpic^,mem[$b800:0],6400);
  1488.       flist.draw;
  1489.     end;
  1490.   end;
  1491. end;
  1492.  
  1493. procedure dolist;
  1494. var
  1495. ch : char;
  1496. n : integer;
  1497. begin
  1498.   move(listpic^,mem[$b800:0],8000);
  1499.   flist.delete;
  1500.   if archive then chdir(temp_path);
  1501.   load;
  1502.   flist.draw;
  1503.   repeat
  1504.     new_mod := false;
  1505.     repeat
  1506.       updateinfo;
  1507.     until keypressed;
  1508.     ch := readkey;
  1509.     case upcase(ch) of
  1510.       'A'..'Z' : begin
  1511.                    flist.gotokey(upcase(ch));
  1512.                  end;
  1513.       #0 : begin
  1514.              ch := readkey;
  1515.              case ch of
  1516.                #72 : flist.upline;
  1517.                #80 : flist.downline;
  1518.                #73 : flist.uppage;
  1519.                #81 : flist.downpage;
  1520.                #71 : flist.gohome;
  1521.                #79 : flist.goend;
  1522.              end;
  1523.            end;
  1524.       ' ' : flist.tagline;
  1525.       #8 : flist.draw;
  1526.       #13 : doit(flist.curline);
  1527.     end;
  1528.   until (ch=#27) or (new_mod);
  1529.   if new_mod then begin
  1530.     strobo_fx := false;
  1531.     for n := 0 to 31 do strobo_sam[n] := false;
  1532.     pan_mode := false;
  1533.   end;
  1534.   fillchar(mem[$b800:0],16000,0);
  1535.   normscr;
  1536. end;
  1537.  
  1538. procedure soita(sam,note : integer);
  1539. var
  1540. freq,vol,st_ofs : integer;
  1541. begin
  1542.   gusstopvoice(13);
  1543.   gussetbalance(13,7);
  1544.   if samples[sam].length < 3 then exit;
  1545.   freq := periods[per_table[samples[sam].ftune,note]];
  1546.   vol := gusvol[samples[sam].volume]*amp_vol+20000;
  1547.   st_ofs := 2;
  1548.   if (samples[sam].loopend > 2) then
  1549.     gusplayall(13,8,gus_addr[sam]+st_ofs,
  1550.                      gus_addr[sam]+samples[sam].loopstart,
  1551.                      gus_addr[sam]+samples[sam].loopend,freq,vol)
  1552.     else gusplayall(13,0,gus_addr[sam]+st_ofs,
  1553.                           gus_addr[sam]+st_ofs,
  1554.                           gus_addr[sam]+samples[sam].length,freq,vol);
  1555. end;
  1556.  
  1557. function key2note(ch : char;okt : integer) : integer;
  1558. var
  1559. note : integer;
  1560. begin
  1561.   case ch of
  1562.     'Q' : note := _C2+okt;
  1563.     'W' : note := _D2+okt;
  1564.     'E' : note := _E2+okt;
  1565.     'R' : note := _F2+okt;
  1566.     'T' : note := _G2+okt;
  1567.     'Y' : note := _A2+okt;
  1568.     'U' : note := _B2+okt;
  1569.     'I' : note := _C3+okt;
  1570.     'O' : note := _D3+okt;
  1571.     'P' : note := _E3+okt;
  1572.     '2' : note := _Db2+okt;
  1573.     '3' : note := _Eb2+okt;
  1574.     '5' : note := _Gb2+okt;
  1575.     '6' : note := _Ab2+okt;
  1576.     '7' : note := _Bb2+okt;
  1577.     '9' : note := _Db3+okt;
  1578.     'Z' : note := _C1+okt;
  1579.     'X' : note := _D1+okt;
  1580.     'C' : note := _E1+okt;
  1581.     'V' : note := _F1+okt;
  1582.     'B' : note := _G1+okt;
  1583.     'N' : note := _A1+okt;
  1584.     'M' : note := _B1+okt;
  1585.     'S' : note := _Db1+okt;
  1586.     'D' : note := _Eb1+okt;
  1587.     'G' : note := _Gb1+okt;
  1588.     'H' : note := _Ab1+okt;
  1589.     'J' : note := _Bb1+okt;
  1590.     else note := 0;
  1591.   end;
  1592.   if note > 48 then dec(note,12);
  1593.   key2note := note;
  1594. end;
  1595.  
  1596. procedure menu;
  1597. var
  1598. ch : char;
  1599. clr : boolean;
  1600. n : integer;
  1601. begin
  1602.   clr := true;
  1603.   start_chn := 0;
  1604.   pause := 0;
  1605.   old_row := 666;
  1606.   start_sample := 1;
  1607.   cur_sample := 1;
  1608.   play_sample := 0;
  1609.   cur_octave := 1;
  1610.   help := false;
  1611.   hide_cursor;
  1612.   getpal(@normpal);
  1613.   setvgapal(col_back,col_backr,col_backg,col_backb);
  1614.   fillchar(listpic^,8000,0);
  1615.   show_pic(0,seg(listpic^),@image6);
  1616.   show_pic(8000+0,$b800,@image1);
  1617.   show_pic((50+5+header.chns)*160,$b800,@image2);
  1618.   if loaded then show_pic(160,$b800,@image3)
  1619.   else show_pic(160,$b800,@image6);
  1620.   for n := 0 to header.chns do
  1621.     move(image4,mem[$b800:(4+n)*160+8000],160);
  1622.   line_comp((header.chns+9)*8);
  1623.   set_scr_ofs(4000);
  1624.   if loaded then start_playing;
  1625.   repeat
  1626.     if loaded then show_ptn(clr);
  1627.     clr := false;
  1628.     if loaded then ch := readkey
  1629.     else ch := #13;
  1630.     if (play_sample <> 0) and (key2note(upcase(ch),cur_octave*12) <> 0) then begin
  1631.       soita(play_sample,key2note(upcase(ch),cur_octave*12));
  1632.       ch := #1;
  1633.     end;
  1634.     if (play_sample <> 0) and (key2note(upcase(ch),cur_octave*12)=0) then begin
  1635.       if (ch = '+') and (cur_octave<2) then inc(cur_octave);
  1636.       if (ch = '-') and (cur_octave>0) then dec(cur_octave);
  1637.       if upcase(ch) in ['A'..'Z','+','-'] then ch := #1;
  1638.     end;
  1639.     case ch of
  1640.       '+' : if amp_vol < 16 then begin
  1641.               inc(amp_vol);
  1642.               for n := 0 to header.chns do
  1643.                 gussetvolume(n,gusvol[channels[n].vol]*amp_vol+20000);
  1644.             end;
  1645.       '-' : if amp_vol > 0 then begin
  1646.               dec(amp_vol);
  1647.               for n := 0 to header.chns do
  1648.                 gussetvolume(n,gusvol[channels[n].vol]*amp_vol+20000);
  1649.             end;
  1650.       ',' : if start_chn > 0 then begin
  1651.               dec(start_chn);
  1652.               clr := true;
  1653.             end;
  1654.       '.' : if start_chn < header.chns-4 then begin
  1655.               inc(start_chn);
  1656.               clr := true;
  1657.             end;  
  1658.       'P','p' : if pause = 0 then begin
  1659.                   pause := speed;
  1660.                   speed := 0;
  1661.                   for n := 0 to maxchn-1 do gusstopvoice(n);
  1662.                   strobo_val := 0;
  1663.                 end else begin
  1664.                   speed := pause;
  1665.                   pause := 0;
  1666.                 end;
  1667.       'R','r' : if playing then begin
  1668.                   stop_playing;
  1669.                   playing := false;
  1670.                 end else begin
  1671.                   clr := true;
  1672.                   start_playing;
  1673.                   playing := true;
  1674.                 end;
  1675.       'V','v' : if vblank then vblank := false
  1676.                 else vblank := true;
  1677.       'b','B' : if strobo_sam[cur_sample]=true then strobo_sam[cur_sample]:=false
  1678.                 else begin
  1679.                   strobo_sam[cur_sample] := true;
  1680.                   strobo_fx := true;
  1681.                 end;
  1682.       'A','a' : if pan_mode then begin
  1683.                   for n := 0 to header.chns-1 do begin
  1684.                     channels[n].pan := defpan[n];
  1685.                     gussetbalance(n,defpan[n]);
  1686.                   end;
  1687.                   pan_mode := false;
  1688.                   pan_cnt := 4*pan_speed;
  1689.                 end
  1690.                 else begin
  1691.                   pan_mode := true;
  1692.                   pan_cnt := 4*pan_speed;
  1693.                   pan_inc := 1;
  1694.                 end;
  1695.       'Q','q' : if qualitymode then begin
  1696.                   qualitymode := false;
  1697.                   makepertbl;
  1698.                   normscr;
  1699.                 end
  1700.                 else begin
  1701.                   qualitymode := true;
  1702.                   makepertbl;
  1703.                   normscr;
  1704.                 end;
  1705.       ' ' : if play_sample <> 0 then begin
  1706.               gussetvolume(13,0);
  1707.               gusstopvoice(13);
  1708.               play_sample := 0;
  1709.             end
  1710.             else play_sample := cur_sample;
  1711.       #13 : dolist;
  1712.       #8 : begin      {bkspc}
  1713.              goto_mod(cur_ptn,0);
  1714.              clr := true;
  1715.            end;
  1716.       #0 : begin
  1717.              ch := readkey;
  1718.              case ch of
  1719.                #81 : if speed < 31 then begin  {pgdn}
  1720.                        inc(nspeed);
  1721.                        inc(speed);
  1722.                      end;
  1723.                #73 : if speed > 0 then begin   {pgup}
  1724.                        dec(nspeed);
  1725.                        dec(speed);
  1726.                      end;
  1727.                #59..#66 : if byte(ch)-59 < header.chns then begin  {F1-F8}
  1728.                             channels[byte(ch)-59].on :=
  1729.                               channels[byte(ch)-59].on xor 1;
  1730.                             gusstopvoice(byte(ch)-59);
  1731.                           end;    
  1732.                #75 : begin    {left arrow}
  1733.                        if cur_ptn > 0 then
  1734.                          goto_mod(cur_ptn-1,0)
  1735.                        else goto_mod(0,0);
  1736.                        clr := true;
  1737.                      end;
  1738.                #77 : begin    {right arrow}
  1739.                        if cur_ptn < header.length-1 then
  1740.                          goto_mod(cur_ptn+1,0)
  1741.                        else goto_mod(cur_ptn,0);
  1742.                        clr := true;
  1743.                      end;
  1744.                #72 : begin {up}
  1745.                        if cur_sample > 1 then dec(cur_sample);
  1746.                        if cur_sample < start_sample then dec(start_sample);
  1747.                        if play_sample <> 0 then play_sample := cur_sample;
  1748.                      end;
  1749.                #80 : begin  {down}
  1750.                        if cur_sample < 31 then inc(cur_sample);
  1751.                        if cur_sample > (start_sample+24-header.chns) then
  1752.                          inc(start_sample);
  1753.                        if play_sample <> 0 then play_sample := cur_sample;
  1754.                      end;
  1755.              end;
  1756.            end;
  1757.       'S','s' : scrsaver;
  1758.       '!' : begin
  1759.               textmode(co80);
  1760.               exec(getenv('COMSPEC'),'');
  1761.               textmode(co80+font8x8);
  1762.               normscr;
  1763.               old_row := 666;
  1764.             end;
  1765.       '"' : begin
  1766.               init_dos;
  1767.               exec(getenv('COMSPEC'),'');
  1768.               end_dos;
  1769.               textmode(co80+font8x8);
  1770.               normscr;
  1771.               old_row := 666;
  1772.             end;
  1773.     end;
  1774.   until (ch = #27) or (not loaded);
  1775.   stop_playing;
  1776. end;
  1777.  
  1778. function exists(s : string) : boolean;
  1779. var
  1780. f : file of byte;
  1781. i : integer;
  1782. begin
  1783.   assign(f,s);
  1784.   {$i-}
  1785.   reset(f);
  1786.   i := ioresult;
  1787.   {$i+}
  1788.   if i = 0 then begin
  1789.     close(f);
  1790.     exists := true;
  1791.   end else exists := false;
  1792. end;
  1793.  
  1794. function addext(str,ext: string) : string;
  1795. begin
  1796.   if pos('.',str) > 0 then addext := str
  1797.   else addext := str+ext;
  1798. end;
  1799.  
  1800. function findgus : word;
  1801. var
  1802. n,c,i : word;
  1803. begin
  1804.   if getenv('ultrasnd') = '' then begin
  1805.     findgus := 0;
  1806.     exit;
  1807.   end;
  1808.   val(copy(getenv('ultrasnd'),1,3),n,c);
  1809.   if c <> 0 then begin
  1810.     findgus := 0;
  1811.     exit;
  1812.   end;
  1813.   case n of
  1814.     210 : i := $210;
  1815.     220 : i := $220;
  1816.     230 : i := $230;
  1817.     240 : i := $240;
  1818.     250 : i := $250;
  1819.     260 : i := $260;
  1820.     270 : i := $270;
  1821.   else begin
  1822.     findgus := 0;
  1823.     exit;
  1824.   end;
  1825. end;
  1826. findgus := i;
  1827. end;
  1828.  
  1829. procedure getcmd;
  1830. var
  1831. s : string;
  1832. b : byte;
  1833. i,n,c : integer;
  1834.  
  1835. begin
  1836.   mod_name :=  '';
  1837.   for n := 0 to 31 do strobo_sam[n] := false;
  1838.   strobo_fx := false;
  1839.   strobo_col[1] := $ff;
  1840.   strobo_col[2] := $ff;
  1841.   strobo_col[3] := $ff;
  1842.   writeln('Adrenalin module player v 0.30  By: Beta/Adrenalin');
  1843.   if paramcount > 0 then for n := 1 to paramcount do begin
  1844.     if copy(paramstr(n),1,1) <> '/' then begin
  1845.       s := addext(paramstr(n),'.mod');
  1846.       if not exists(s) then begin
  1847.         writeln('Module ',s,' not found!');
  1848.         halt(2);
  1849.       end;
  1850.       mod_name := s;
  1851.     end
  1852.     else if copy(paramstr(n),1,5) = '/port' then begin
  1853.       s := copy(paramstr(n),6,3);
  1854.       if s = '210' then base := $210;
  1855.       if s = '220' then base := $220;
  1856.       if s = '230' then base := $230;
  1857.       if s = '240' then base := $240;
  1858.       if s = '250' then base := $250;
  1859.       if s = '260' then base := $260;
  1860.       if s = '270' then base := $270;
  1861.     end
  1862.     else if copy(paramstr(n),1,5)='/ssam' then begin
  1863.       val(copy(paramstr(n),6,2),i,c);
  1864.       if (i > 0) and (i < 32) then begin
  1865.         strobo_fx := true;
  1866.         strobo_sam[i] := true;
  1867.       end;
  1868.     end
  1869.     else if copy(paramstr(n),1,5)='/scol' then begin
  1870.       strobo_col[1] := 0;
  1871.       strobo_col[2] := 0;
  1872.       strobo_col[3] := 0;
  1873.       val(copy(paramstr(n),6,2),i,c);
  1874.       if (i > 0) and (i < 8) then begin
  1875.         if i and 1 > 0 then strobo_col[3] := $ff;
  1876.         if i and 2 > 0 then strobo_col[2] := $ff;
  1877.         if i and 4 > 0 then strobo_col[1] := $ff;
  1878.       end;
  1879.     end
  1880.     else if copy(paramstr(n),1,5)='/sspd' then begin
  1881.       val(copy(paramstr(n),6,2),i,c);
  1882.       if i > 0 then strobo_speed := i;
  1883.     end
  1884.     else if copy(paramstr(n),1,5)='/pspd' then begin
  1885.       val(copy(paramstr(n),6,2),i,c);
  1886.       if i > 0 then pan_speed := i;
  1887.       pan_cnt := 4*pan_speed;
  1888.     end
  1889.     else if copy(paramstr(n),1,2)='/?' then begin
  1890.       writeln('Usage: ADNMOD modname [options]');
  1891.       writeln('options:  /portxxx    set gus address');
  1892.       writeln('          /scolx      set strobo color');
  1893.       writeln('          /ssamxx     set strobo sample');
  1894.       writeln('          /sspdxx     set strobo speed');
  1895.       halt(0);
  1896.     end;
  1897.   end;
  1898. end;
  1899.  
  1900. procedure initialize;
  1901. begin
  1902.   if base = $200 then if findgus > 0 then base := findgus;
  1903.   gusfind;
  1904.   if base = $200 then begin
  1905.     writeln('GUS not found. Assuming address 220');
  1906.     base := $220;
  1907.     gusfind;
  1908.   end;
  1909.   write('GUS found at ',nibb2hex(hi(base)),byte2hex(lo(base)));
  1910.   gusmem := gusfindmem;
  1911.   writeln(' with ',gusmem,' bytes of memory');
  1912.   gusreset;
  1913.   move(per_table,oldpertbl,sizeof(per_table));
  1914.   normkbf := mem[$40:$17];
  1915. end;
  1916.  
  1917. procedure showerr(error : integer);
  1918. begin
  1919.   case error of
  1920.     1 : writeln('Too many channels');
  1921.     2 : begin
  1922.           writeln;
  1923.           writeln('Load error!');
  1924.         end;
  1925.     3 : begin
  1926.           writeln;
  1927.           writeln('Out of memory');
  1928.         end;
  1929.     255 : writeln('Error');
  1930.   end;
  1931. end;
  1932.  
  1933. var
  1934. i,n : integer;
  1935. per : real;
  1936.  
  1937. begin
  1938.   randomize;
  1939.   checkbreak := false;
  1940.   getcmd;
  1941.   initialize;
  1942.   init_mod;
  1943.   if initxms <> 0 then begin
  1944.     writeln('XMS not found');
  1945.     halt(3);
  1946.   end;
  1947.   if mod_name <> '' then begin
  1948.     load_mod(mod_name,true);
  1949.     if mod_error <> 0 then begin
  1950.       showerr(mod_error);
  1951.       halt(mod_error);
  1952.     end;
  1953.   end;
  1954.   textmode(co80+font8x8);
  1955.   initlist;
  1956.   menu;
  1957.   chdir(temp_path);
  1958.   delall;
  1959.   chdir(org_path);
  1960.   freemem(lpic,8000);
  1961.   free_mod;
  1962.   if isxms then donexms;
  1963.   gusdeinit;
  1964.   textmode(co80);
  1965.   mem[$40:$17] := 0;
  1966.   if mod_error <> 0 then showerr(mod_error);
  1967.   if virt_info.err_wptn <> -1 then begin
  1968.     writeln('Error in warnptn. Please report error numbers and module name to author');
  1969.     writeln('cptn: ',virt_info.err_cptn);
  1970.     writeln('wptn: ',virt_info.err_wptn);
  1971.     writeln('nptn: ',virt_info.err_nptn);
  1972.   end;
  1973.   writeln('Thank you for using ADNMOD 0.30');
  1974. end.
  1975.